package org.ktm.utils;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

public class Resources {

    protected static HashMap<String, ResourceBundle> bundleCache;

    protected static final String                    bundleName         = Localizer.RESOURCE_BUNDLE_NAME_DEFAULT;
    protected static final String                    USERDEFINED_BUNDLE = bundleName + "Custom";

    public Resources() {
        if (bundleCache == null) {
            bundleCache = new HashMap<String, ResourceBundle>();
        }
    }

    public String formatString(String key, String msgString, Object[] args) {
        MessageFormat format = null;
        if (msgString != null) {
            format = new MessageFormat(msgString);
            return format.format(args);
        }
        return "???" + key + "???";
    }

    public String getString(String key) {
        return getString(key, this.getClass());
    }

    public String getString(ParameterizedError error) {
        return getString(error.getKey(), error.getValues());
    }

    public String getString(String key, ParameterizedError parameterizedError) {
        return getString(key, parameterizedError, Localizer.getCurrentLocale());
    }

    public String getString(String key, ParameterizedError parameterizedError, Locale locale) {
        Class<?> clazz = parameterizedError.getClass();
        String msg = getString(key, locale, bundleName, clazz);

        return formatString(key, msg, parameterizedError.getValues());
    }

    public String getString(String key, Exception exception) {
        return getString(key, exception, null);
    }

    public String getString(String key, Exception exception, Locale locale) {
        if (locale == null) {
            locale = Localizer.getCurrentLocale();
        }
        if (exception instanceof ParameterizedError) {
            return getString(key, (ParameterizedError) exception, locale);
        } else {
            return getString(key, bundleName, locale, exception.getClass());
        }
    }

    public String getString(String key, Object[] args) {
        return formatString(key, getString(key), args);
    }

    protected String getString(String key, Locale locale, String baseName, Class<?> clazz) {
        String msg = null;
        ResourceBundle bundle;
        String customBundleName = getCustomBundleName();

        if (customBundleName != null) {
            try {
                bundle = getBundle(customBundleName, locale, clazz);
                if (bundle != null) {
                    msg = bundle.getString(key);
                }
            } catch (MissingResourceException mre) {
                // No custom resource bundle found; just rely on the default
                // resource bundle
            }
        }
        if (msg == null) {
            bundle = getBundle(baseName, locale, clazz);
            if (bundle == null) return null;

            msg = bundle.getString(key);
        }
        return msg;
    }

    protected String getString(String key, String bundleName, Locale locale, Class<?> clazz) {
        return getString(key, locale, bundleName, clazz);
    }

    public String getString(String key, Class<?> clazz) {
        return getString(key, bundleName, Localizer.getCurrentLocale(), clazz);
    }

    protected String getPackageName(Class<?> clazz) {
        String packageName = null;
        Package myPackage = clazz.getPackage();
        if (myPackage == null) {
            String className = clazz.getName();
            int lastDot = className.lastIndexOf('.');
            packageName = className.substring(0, lastDot);
        } else {
            packageName = myPackage.getName();
        }
        return packageName;
    }

    protected String getCustomBundleName() {
        return USERDEFINED_BUNDLE;
    }

    protected ResourceBundle getBundle(String baseName, Locale locale, Class<?> clazz) {
        String bundleKey = getBaseName(clazz, getBundleKey(baseName, locale));
        ResourceBundle rscBundle = (ResourceBundle) bundleCache.get(bundleKey);

        // If the bundle for the current package isn't in the cache, load it and
        // put it there
        if (rscBundle == null) {
            rscBundle = Localizer.getResourceBundle(locale, clazz, baseName);
            bundleCache.put(bundleKey, rscBundle);
        }
        return rscBundle;
    }

    protected String getBundleKey(String baseName, Locale locale) {
        return baseName + "_" + locale.toString();
    }

    protected String getBaseName(Class<?> clazz, String bundleName) {
        return getPackageName(clazz) + "." + bundleName;
    }
}
